home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / manchest.lha / MANCHESTER / manchester / 2.2 / SystemMonitor=2.2.st < prev    next >
Text File  |  1993-07-24  |  51KB  |  1,647 lines

  1. "    NAME        SystemMonitor=2.2
  2.     AUTHOR        tph@cs.man.ac.uk
  3.     FUNCTION much better PerfMeter 
  4.     ST-VERSIONS    2.1
  5.     PREREQUISITES    screendump 
  6.     CONFLICTS    
  7.     DISTRIBUTION      world
  8.     VERSION        1.1
  9.     DATE    22 Jan 1989
  10. SUMMARY    SystemMonitor
  11.     is Trevor's equivalent of a PerfMeter.  This is a
  12.    new version, with lots of additional bells and whistles.  In
  13.    particular, it provides a proper model (a process called
  14.    SystemMonitor which runs all the time) and a hierarchy of
  15.    views to display the traces in a variety of ways.
  16.    Two different useful views are provided:
  17.  
  18.    ""MonitorView open"" gives a single small view on one trace.
  19.    ""LargeMonitorView open"" gives a view on all traces.
  20.  
  21.    Note    that menus are attached to all three mouse buttons!
  22.    Also, this goodie should be filed in after screendump.st.
  23.  
  24.    *** If you have the old version of the system monitor filed in,
  25.    make sure you remove the old classes MonitorView and 
  26.    MonitorController before filing in the new version! ***
  27.    (2.1). TPH
  28. "!
  29. 'From Smalltalk-80, version 2, of April 1, 1983 on 23 July 1987 at 7:50:45 am'!
  30.  
  31.  
  32.  
  33. !ProcessorScheduler methodsFor: 'accessing'!
  34.  
  35. quiescentProcesses
  36.     "Answer the array of LinkedLists which represents the
  37.      suspended processes."
  38.  
  39.     ^quiescentProcessLists! !
  40.  
  41. 'From Smalltalk-80, version 2, of April 1, 1983 on 23 July 1987 at 7:50:50 am'!
  42.  
  43.  
  44.  
  45. !ProcessorScheduler methodsFor: 'accessing'!
  46.  
  47. quiescentProcessesAt: aPriority 
  48.     "Answer the LinkedList which represents the suspended processes  
  49.      at the given priority level."
  50.  
  51.     ^quiescentProcessLists at: aPriority! !
  52.  
  53. 'From Smalltalk-80, version 2, of April 1, 1983 on 22 July 1987 at 5:54:37 pm'!
  54.  
  55.  
  56.  
  57. !ProcessorScheduler methodsFor: 'accessing'!
  58.  
  59. noOfProcesses
  60.     "Answer with the number of runnable processes in the system.
  61.      Includes the process which is currently active."
  62.  
  63.     | count |
  64.     count _ 1.
  65.     1 to: self highestPriority do: [ :each |
  66.         count _ count + (self quiescentProcessesAt: each) size].
  67.     ^count! !
  68.  
  69. MouseMenuController subclass: #MonitorController
  70.     instanceVariableNames: ''
  71.     classVariableNames: 'MonitorRedButtonMenu MonitorRedButtonMessages MonitorYellowButtonMenu MonitorYellowButtonMessages '
  72.     poolDictionaries: ''
  73.     category: 'Monitoring'!
  74. MonitorController comment:
  75. 'I am a controller for MonitorViews.  I have both red and yellow button
  76. menus which allow the displayed history and the display style to be changed.
  77. '!
  78.  
  79.  
  80. !MonitorController methodsFor: 'initialize-release'!
  81.  
  82. initialize
  83.     "Initialize the red and yellow button menus."
  84.  
  85.     self
  86.         redButtonMenu: MonitorRedButtonMenu
  87.         redButtonMessages: MonitorRedButtonMessages.
  88.     self
  89.         yellowButtonMenu: MonitorYellowButtonMenu
  90.         yellowButtonMessages: MonitorYellowButtonMessages.! !
  91.  
  92. !MonitorController methodsFor: 'control defaults'!
  93.  
  94. isControlActive
  95.  
  96.     ^(view containsPoint: sensor cursorPoint) & sensor blueButtonPressed not! !
  97.  
  98. !MonitorController methodsFor: 'menu messages'!
  99.  
  100. changeDisplayRate
  101.     "Change the display rate, in multiples of the monitor process interval."
  102.  
  103.     | anAnswer |
  104.     anAnswer _ FillInTheBlank request: ' New Display Rate (in seconds)? '
  105.                 initialAnswer: self view displayInterval printString.
  106.     anAnswer isEmpty ifFalse: [
  107.         self view displayInterval: (Number readFrom: (ReadStream on: anAnswer)).
  108.         self view display]!
  109.  
  110. changeNoOfPoints
  111.     "Ask the user for a new number of points to be displayed
  112.      and set the new value."
  113.  
  114.     | anAnswer tempArray |
  115.     anAnswer _ FillInTheBlank request: ' Number of points to be displayed? '
  116.                 initialAnswer: self view displayPoints printString.
  117.     anAnswer isEmpty ifFalse: [
  118.         self view displayPoints: (Number readFrom: (ReadStream on: anAnswer)).
  119.         self view display]!
  120.  
  121. displayBitBltCount
  122.     "Set the current display to be the number of BitBlt operations."
  123.  
  124.     self makeDisplay: #bitblt!
  125.  
  126. displayCPULoad
  127.     "Set the current display to be processor load."
  128.  
  129.     self makeDisplay: #cpu!
  130.  
  131. displayDifferences
  132.     "Set the current display mode to be difference histograms."
  133.  
  134.     self makeStyle: #difference!
  135.  
  136. displayFileActivity
  137.     "Set the current display to be the number of File operations. Actually,
  138.      this is the number of Unix system calls, but we cannot do anything
  139.      else at the moment...."
  140.  
  141.     self makeDisplay: #files!
  142.  
  143. displayFreeMemory
  144.     "Set the current display to be free memory."
  145.  
  146.     self makeDisplay: #memory!
  147.  
  148. displayFreeOops
  149.     "Set the current display to be free oops."
  150.  
  151.     self makeDisplay: #oops!
  152.  
  153. displayGraph
  154.     "Set the current display mode to be graphs."
  155.  
  156.     self makeStyle: #graph!
  157.  
  158. displayHistogram
  159.     "Set the current display mode to be Histograms."
  160.  
  161.     self makeStyle: #histogram!
  162.  
  163. displayInputEvents
  164.     "Set the current display to be input events."
  165.  
  166.     self makeDisplay: #input!
  167.  
  168. displayProcesses
  169.     "Set the current display to be the number of processes."
  170.  
  171.     self makeDisplay: #process!
  172.  
  173. displayStripChart
  174.     "Set the current display mode to be a bar chart."
  175.  
  176.     self makeStyle: #barchart! !
  177.  
  178. !MonitorController methodsFor: 'private'!
  179.  
  180. makeDisplay: aSymbol
  181.     "Make the corresponding view display the history indicated by aSymbol."
  182.  
  183.     self view currentDisplay: aSymbol.
  184.     self view display!
  185.  
  186. makeStyle: aSymbol
  187.     "Make the corresponding view use the style indicated by aSymbol."
  188.  
  189.     self view currentStyle: aSymbol.
  190.     self view buildSubViews.
  191.     self view display! !
  192. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  193.  
  194. MonitorController class
  195.     instanceVariableNames: ''!
  196.  
  197.  
  198. !MonitorController class methodsFor: 'class initialization'!
  199.  
  200. initialize
  201.     "Initialize the red and yellow button menus."
  202.  
  203.     MonitorYellowButtonMenu _ PopUpMenu labels:
  204.         'cpu load\processes\free memory\free oops\input events\bitblt\file i/o' withCRs.
  205.     MonitorYellowButtonMessages _
  206.         #(displayCPULoad displayProcesses displayFreeMemory displayFreeOops
  207.            displayInputEvents displayBitBltCount displayFileActivity).
  208.  
  209.     MonitorRedButtonMenu _ PopUpMenu labels:
  210.         'update interval\number of points\histogram\differences\line graph\strip chart' withCRs lines: #(2).
  211.     MonitorRedButtonMessages _
  212.         #(changeDisplayRate changeNoOfPoints
  213.            displayHistogram displayDifferences displayGraph displayStripChart).
  214.  
  215.     "MonitorController initialize."! !
  216.  
  217. MonitorController initialize!
  218.  
  219.  
  220. MonitorController subclass: #LargeMonitorController
  221.     instanceVariableNames: ''
  222.     classVariableNames: ''
  223.     poolDictionaries: ''
  224.     category: 'Monitoring'!
  225. LargeMonitorController comment:
  226. 'I am a controller for LargeMonitorViews.  I have a red button menu
  227. allowing the display style to be changed, but no yellow button menu.
  228. '!
  229.  
  230.  
  231. !LargeMonitorController methodsFor: 'initialize-release'!
  232.  
  233. initialize
  234.     "Initialize the red button menu.  The yellow button is not used."
  235.  
  236.     self
  237.         redButtonMenu: MonitorRedButtonMenu
  238.         redButtonMessages: MonitorRedButtonMessages! !
  239.  
  240. Object subclass: #Monitor
  241.     instanceVariableNames: 'activityCount activityHistory inputCount inputHistory bitBltCount bitBltHistory fileCount fileHistory coreHistory oopsHistory processHistory monitorProcess delayInterval maxLength '
  242.     classVariableNames: 'DefaultDelayInterval DefaultHistoryLength MaxPollsPerSecond '
  243.     poolDictionaries: ''
  244.     category: 'Monitoring'!
  245. Monitor comment:
  246. 'I provide a mechanism for monitoring various activities within Smalltalk.  I maintain
  247. various counts and a history of such counts.  There should be exactly one
  248. instance of me (called SystemMonitor) in the system.
  249.  
  250. activityCount        A count of how often the mouse buttons are polled.  This
  251.                     gives a (very vague!!) indication of the level of activity in
  252.                     the system.  The higher the count, the less activity is
  253.                     going on.
  254.  
  255. activityHistory        <OrderedCollection> of activity counts.
  256.  
  257. inputCount            A count of input events (keyboard and mouse buttons).  Does
  258.                     not include mouse X/Y movement.
  259.  
  260. inputHistory        <OrderedCollection> of input counts.
  261.  
  262. bitBltCount            A count of graphics operations performed (especially BitBlt).
  263.  
  264. bitBltHistory        <OrderedCollection> of BitBlt counts.
  265.  
  266. fileCount            A count of Unix I/O operations, especially file I/O.
  267.  
  268. fileHistory            <OrderedCollection> of I/O counts.
  269.  
  270. coreHistory            <OrderedCollection> of core left counts.
  271.  
  272. oopsHistory            <OrderedCollection> of oops left counts.
  273.  
  274. monitorProcess        <Process> which runs to gather the history information.
  275.  
  276. delayInterval        The time (in seconds) between activations of the monitor
  277.                     process.
  278. '!
  279.  
  280.  
  281. !Monitor methodsFor: 'initialize-release'!
  282.  
  283. initialize
  284.     "Initialize the counts and histories.  Start the monitoring process."
  285.  
  286.     activityCount _ 0.
  287.     inputCount _ 0.
  288.     bitBltCount _ 0.
  289.     fileCount _ 0.
  290.  
  291.     activityHistory _ OrderedCollection new.
  292.     inputHistory _ OrderedCollection new.
  293.     bitBltHistory _ OrderedCollection new.
  294.     fileHistory _ OrderedCollection new.
  295.     coreHistory _ OrderedCollection new.
  296.     oopsHistory _ OrderedCollection new.
  297.     processHistory _ OrderedCollection new.
  298.  
  299.     delayInterval _ DefaultDelayInterval.
  300.     maxLength _ DefaultHistoryLength.
  301.  
  302.     self initializeProcess.    "Initialize the process."
  303.     monitorProcess resume.    "Start the process."! !
  304.  
  305. !Monitor methodsFor: 'history access'!
  306.  
  307. activityHistory
  308.     "Answer with a copy of the OrderedCollection of counts of general activity."
  309.  
  310.     ^activityHistory copy!
  311.  
  312. bitBltHistory
  313.     "Answer with a copy of the OrderedCollection of counts of bitBlt events."
  314.  
  315.     ^bitBltHistory copy!
  316.  
  317. coreHistory
  318.     "Answer with a copy of the OrderedCollection of counts of remaining memory."
  319.  
  320.     ^coreHistory copy!
  321.  
  322. fileHistory
  323.     "Answer with a copy of the OrderedCollection of counts of Unix file I/O events."
  324.  
  325.     ^fileHistory copy!
  326.  
  327. inputHistory
  328.     "Answer with a copy of the OrderedCollection of counts of input events."
  329.  
  330.     ^inputHistory copy!
  331.  
  332. latestActivity
  333.     "Answer with the most up to date activity count."
  334.  
  335.     activityHistory isEmpty ifTrue: [^0].
  336.     ^activityHistory last!
  337.  
  338. latestBitBlt
  339.     "Answer with the most up to date BitBlt count."
  340.  
  341.     bitBltHistory isEmpty ifTrue: [^0].
  342.     ^bitBltHistory last!
  343.  
  344. latestCore
  345.     "Answer with the most up to date remaing core count."
  346.  
  347.     coreHistory isEmpty ifTrue: [^0].
  348.     ^coreHistory last!
  349.  
  350. latestFile
  351.     "Answer with the most up to date Unix I/O count."
  352.  
  353.     fileHistory isEmpty ifTrue: [^0].
  354.     ^fileHistory last!
  355.  
  356. latestInput
  357.     "Answer with the most up to date input event count."
  358.  
  359.     inputHistory isEmpty ifTrue: [^0].
  360.     ^inputHistory last!
  361.  
  362. latestOops
  363.     "Answer with the most up to date remaing object pointer count."
  364.  
  365.     oopsHistory isEmpty ifTrue: [^0].
  366.     ^oopsHistory last!
  367.  
  368. latestProcess
  369.     "Answer with the most up to date process count."
  370.  
  371.     processHistory isEmpty ifTrue: [^0].
  372.     ^processHistory last!
  373.  
  374. oopsHistory
  375.     "Answer with a copy of the OrderedCollection of counts of remaining object pointers."
  376.  
  377.     ^oopsHistory copy!
  378.  
  379. processHistory
  380.     "Answer with a copy of the OrderedCollection of numbers of processes."
  381.  
  382.     ^processHistory copy! !
  383.  
  384. !Monitor methodsFor: 'process access'!
  385.  
  386. delayInterval
  387.     "Answer with the delay interval (seconds) in use."
  388.  
  389.     ^delayInterval!
  390.  
  391. priority: anInteger
  392.     "Change the priority of the monitoring process.  Normally, the
  393.      monitor process runs at user priority.  However, it may be
  394.      useful to increase the priority when monitoring code which
  395.      runs for a long time."
  396.  
  397.     monitorProcess priority: anInteger.
  398.  
  399.     "Higher priority"
  400.     "SystemMonitor priority: Processor userInterruptPriority."
  401.  
  402.     "Normal Priority"
  403.     "SystemMonitor priority: Processor userSchedulingPriority."!
  404.  
  405. resume
  406.     "Resume the monitoring process."
  407.  
  408.     monitorProcess resume
  409.  
  410.     "SystemMonitor resume."!
  411.  
  412. suspend
  413.     "Suspend the monitoring process.  Under normal circumstances,
  414.      we would like the monitoring process to run all the time."
  415.  
  416.     monitorProcess suspend
  417.  
  418.     "SystemMonitor suspend."!
  419.  
  420. terminate
  421.     "Terminate the monitoring process.  Under normal circumstances,
  422.      we would like the monitoring process to run all the time.  However,
  423.      we might want to stop it for efficiency reasons."
  424.  
  425.     monitorProcess terminate.
  426.  
  427.     "SystemMonitor terminate."! !
  428.  
  429. !Monitor methodsFor: 'counting'!
  430.  
  431. incrementActivityCount
  432.  
  433.     activityCount _ activityCount + 1!
  434.  
  435. incrementBitBltCount
  436.  
  437.     bitBltCount _ bitBltCount + 1!
  438.  
  439. incrementFileCount
  440.  
  441.     fileCount _ fileCount + 1!
  442.  
  443. incrementInputCount
  444.  
  445.     inputCount _ inputCount + 1! !
  446.  
  447. !Monitor methodsFor: 'private'!
  448.  
  449. initializeProcess
  450.     "Sets up the monitoring process."
  451.  
  452.     monitorProcess _ [[
  453.         (Delay forMilliseconds: delayInterval * 1000) wait.
  454.         activityHistory addLast: MaxPollsPerSecond  * delayInterval - activityCount.
  455.         activityCount _ 0.
  456.         (activityHistory size > maxLength) ifTrue: [
  457.             activityHistory removeFirst].
  458.         inputHistory addLast: inputCount.
  459.         inputCount _ 0.
  460.         (inputHistory size > maxLength) ifTrue: [
  461.             inputHistory removeFirst].
  462.         bitBltHistory addLast: bitBltCount.
  463.         bitBltCount _ 0.
  464.         (bitBltHistory size > maxLength) ifTrue: [
  465.             bitBltHistory removeFirst].
  466.         fileHistory addLast: fileCount.
  467.         fileCount _ 0.
  468.         (fileHistory size > maxLength) ifTrue: [
  469.             fileHistory removeFirst].
  470.         coreHistory addLast: Smalltalk coreLeft.
  471.         (coreHistory size > maxLength) ifTrue: [
  472.             coreHistory removeFirst].
  473.         oopsHistory addLast: Smalltalk oopsLeft.
  474.         (oopsHistory size > maxLength) ifTrue: [
  475.             oopsHistory removeFirst].
  476.         processHistory addLast: Processor noOfProcesses.
  477.         (processHistory size > maxLength) ifTrue: [
  478.             processHistory removeFirst].
  479.         self changed: self.
  480.         true] whileTrue] newProcess! !
  481. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  482.  
  483. Monitor class
  484.     instanceVariableNames: ''!
  485.  
  486.  
  487. !Monitor class methodsFor: 'instance creation'!
  488.  
  489. new
  490.     "Answer with a new instance of me, but only if no such instance 
  491.     already  exists."
  492.  
  493.     | count |
  494.     count _ self instanceCount.
  495.     count = 0 ifTrue: [^super new initialize].
  496.     count = 1 ifTrue: [^self error: 'Only one instance of Monitor allowed'].
  497.     count > 1 ifTrue: [^self error: 'More than one Monitor running -- this can''t happen!!']! !
  498.  
  499. !Monitor class methodsFor: 'class initialization'!
  500.  
  501. initialize
  502.     "Initialize the default delay time for the monitoring process and the
  503.      default history length."
  504.  
  505.     DefaultDelayInterval _ 5.
  506.     DefaultHistoryLength _ 100.
  507.     MaxPollsPerSecond _ 850.    "Kludge factor to get rough
  508.                                  measure of processor utilization."
  509.  
  510.     "Monitor initialize."! !
  511.  
  512. Monitor initialize!
  513. Transcript show: 'Initializing SystemMonitor'; cr.
  514. Smalltalk declare: #SystemMonitor from: Undeclared.
  515. SystemMonitor _ Monitor new.!
  516.  
  517.  
  518. View subclass: #CollectionView
  519.     instanceVariableNames: ''
  520.     classVariableNames: ''
  521.     poolDictionaries: ''
  522.     category: 'Monitoring'!
  523. CollectionView comment:
  524. 'I am an abstract superclass of views which know how to display the
  525. contents of an ordered collection in various ways.
  526. '!
  527.  
  528.  
  529. !CollectionView methodsFor: 'controller access'!
  530.  
  531. defaultControllerClass
  532.     "I never want control."
  533.  
  534.     ^NoController! !
  535.  
  536. !CollectionView methodsFor: 'displaying'!
  537.  
  538. displayCollection: aCollection maxPoints: noOfPoints inBox: aRectangle scale: scaleFactor 
  539.     "Display aCollection as some type of visible representation in 
  540.      aRectangle, with the scale factor given. Limit the display to a 
  541.      maximum of noOfPoints."
  542.  
  543.     self subclassResponsibility!
  544.  
  545. displayView
  546.     "Display the collection indicated by currentDisplay in my superview."
  547.  
  548.     self
  549.         displayCollection: (self
  550.                 subtractFrom: self superView currentCollection
  551.                 amount: self superView currentLower)
  552.         maxPoints: self superView displayPoints
  553.         inBox: self insetDisplayBox
  554.         scale: self superView currentUpper - self superView currentLower! !
  555.  
  556. !CollectionView methodsFor: 'private'!
  557.  
  558. averageOf: aCollection 
  559.     "Answer with the arithmetic mean of the numbers in aCollection."
  560.  
  561.     | total |
  562.     total _ 0.
  563.     aCollection do: [:x | total _ total + x].
  564.     ^(total / aCollection size) asFloat!
  565.  
  566. pad: aCollection to: aSize
  567.     "If the size of aCollection is less than aSize, pad it
  568.      out by duplicating the first element.  If the size of
  569.      aCollection is greater than aSize, truncate aCollection
  570.      by removing some elements from the start."
  571.  
  572.     | firstValue |
  573.     (aCollection size = aSize) ifTrue: [^self].
  574.     (aCollection size < aSize)
  575.         ifTrue: [
  576.             firstValue _ aCollection first.
  577.             [aCollection size < aSize]
  578.                 whileTrue: [aCollection addFirst: firstValue]]
  579.         ifFalse: [
  580.             [aCollection size > aSize]
  581.                 whileTrue: [aCollection removeFirst]]!
  582.  
  583. subtractFrom: aCollection amount: aNumber 
  584.     "Answer with a collection like aCollection which has aNumber 
  585.      subtracted from each of it elements."
  586.  
  587.     ^aCollection collect: [:each | each - aNumber]! !
  588.  
  589. CollectionView subclass: #BarStripView
  590.     instanceVariableNames: ''
  591.     classVariableNames: ''
  592.     poolDictionaries: ''
  593.     category: 'Monitoring'!
  594. BarStripView comment:
  595. 'I am a concrete class which knows how to display a collection
  596. as an average + current block display.'!
  597.  
  598.  
  599. !BarStripView methodsFor: 'displaying'!
  600.  
  601. displayCollection: aCollection maxPoints: noOfPoints inBox: aRectangle scale: scaleFactor 
  602.     "Draws an appropriately scaled 'current and average' barchart 
  603.      corresponding to the orderedCollection aCollection, in the box 
  604.      aRectangle on the Display.  The last value in aCollection 
  605.      is displayed in black, and the average of aCollection is 
  606.      displayed in light gray; the border colour is also black. 
  607.      The actual contents of the ordered collection are displayed; 
  608.      the noOfPoints parameter is ignored and included only for 
  609.      compatibility."
  610.  
  611.     self
  612.         displayCollection: aCollection
  613.         maxPoints: noOfPoints
  614.         inBox: aRectangle
  615.         scale: scaleFactor
  616.         currentColor: Form black
  617.         averageColor: Form lightGray
  618.         borderColor: Form black!
  619.  
  620. displayCollection: aCollection maxPoints: noOfPoints inBox: aRectangle scale: scaleFactor currentColor: curCol averageColor: avCol borderColor: borderCol 
  621.     "Draws an appropriately scaled 'current and average' barchart 
  622.      corresponding to the orderedCollection aCollection, in the box 
  623.      aRectangle on the Display.  The last value in aCollection 
  624.      is displayed using curCol, and the average of aCollection is 
  625.      displayed using avCol; the border colour is given by borderCol. 
  626.      The actual contents of the ordered collection are displayed; 
  627.      the noOfPoints parameter is ignored and included only for 
  628.      compatibility."
  629.  
  630.     self
  631.         displayCollection: aCollection
  632.         on: Display
  633.         maxPoints: noOfPoints
  634.         inBox: aRectangle
  635.         scale: scaleFactor
  636.         currentColor: curCol
  637.         averageColor: avCol
  638.         borderColor: borderCol!
  639.  
  640. displayCollection: aCollection on: aDisplayMedium maxPoints: noOfPoints inBox: aRectangle scale: scaleFactor currentColor: curCol averageColor: avCol borderColor: borderCol
  641.     "Draws an appropriately scaled 'current and average' barchart
  642.      corresponding to the orderedCollection aCollection, in the box
  643.      aRectangle on aDisplayMedium.  The last value in aCollection
  644.      is displayed using curCol, and the average of aCollection is
  645.      displayed using avCol; the border colour is given by borderCol.
  646.      The actual contents of the ordered collection are displayed;
  647.      the noOfPoints parameter is ignored and included only for
  648.      compatibility."
  649.  
  650.     | height width average avQuad curQuad refPoint |
  651.     height _ aRectangle height asFloat.
  652.     width _ aRectangle width asFloat.
  653.     average _ self averageOf: aCollection.
  654.     avQuad _ Quadrangle new borderWidth: 1.
  655.     avQuad insideColor: avCol; borderColor: borderCol.
  656.     avQuad left: 0; top: (height / 6) truncated; bottom: (height * 5 / 6) truncated.
  657.     avQuad right: ((average * width / scaleFactor) truncated max: 1).
  658.     curQuad _ Quadrangle new borderWidth: 1.
  659.     curQuad insideColor: curCol; borderColor: borderCol.
  660.     curQuad left: 0; top: (height * 2 / 6) truncated.
  661.     curQuad bottom: (height * 4 / 6) truncated.
  662.     curQuad right: ((aCollection last * width / scaleFactor) truncated max: 1).
  663.     refPoint _ 0@height.
  664.     avQuad
  665.         displayOn: aDisplayMedium
  666.         align: refPoint
  667.         with: aRectangle bottomLeft
  668.         clippingBox: aRectangle.
  669.     curQuad
  670.         displayOn: aDisplayMedium
  671.         align: refPoint
  672.         with: aRectangle bottomLeft
  673.         clippingBox: aRectangle.! !
  674.  
  675. CollectionView subclass: #CollectionLabelView
  676.     instanceVariableNames: ''
  677.     classVariableNames: ''
  678.     poolDictionaries: ''
  679.     category: 'Monitoring'!
  680. CollectionLabelView comment:
  681. 'I know how to display suitable labels and ranges for collections representing
  682. histories within the system.
  683. '!
  684.  
  685.  
  686. !CollectionLabelView methodsFor: 'displaying'!
  687.  
  688. displayText
  689.     "Answer with a DisplayText corresponding to the current history."
  690.  
  691.     | disp |
  692.     disp _ self superView currentDisplay.
  693.     disp == #bitblt ifTrue: [
  694.         ^('BitBlt operations: ' , self superView currentLower printString ,
  695.         ' - ' , self superView currentUpper printString) asDisplayText].
  696.     disp == #memory ifTrue: [
  697.         ^('Free Memory: ', (self superView currentLower // 1000) printString ,
  698.         'k - ', (self superView currentUpper // 1000) printString, 'k') asDisplayText].
  699.     disp == #oops ifTrue: [
  700.         ^('Free Oops: ', self superView currentLower printString ,
  701.         ' - ', self superView currentUpper printString) asDisplayText].
  702.     disp == #input ifTrue: [
  703.         ^('Input events: ', self superView currentLower printString ,
  704.         ' - ', self superView currentUpper printString) asDisplayText].
  705.     disp == #files ifTrue: [
  706.         ^('File operations: ', self superView currentLower printString ,
  707.         ' - ', self superView currentUpper printString) asDisplayText].
  708.     disp == #cpu ifTrue: [
  709.         ^'Processor Activity' asDisplayText].
  710.     disp == #process ifTrue: [
  711.         ^('Processes: ', self superView currentLower printString,
  712.         ' - ', self superView currentUpper printString) asDisplayText].
  713.     ^self error: 'Attempt to display a non-existant history'!
  714.  
  715. displayView
  716.     "Display a label appropriate for the history currently displayed."
  717.  
  718.     self displayText
  719.         displayOn: Display
  720.         at: self insetDisplayBox topLeft
  721.         clippingBox: self insetDisplayBox! !
  722.  
  723. !CollectionLabelView methodsFor: 'accessing'!
  724.  
  725. currentDisplay
  726.     "Answer with a symbol representing the currently displayed history."
  727.  
  728.     ^currentDisplay!
  729.  
  730. currentDisplay: aSymbol
  731.     "Set the history displayed to aSymbol"
  732.  
  733.     currentDisplay _ aSymbol!
  734.  
  735. currentLower
  736.     "Answer with the current lower scale."
  737.  
  738.     ^currentLower!
  739.  
  740. currentLower: aNumber
  741.     "Set the current lower scale."
  742.  
  743.     currentLower _ aNumber!
  744.  
  745. currentUpper
  746.     "Answer with the current upper scale."
  747.  
  748.     ^currentUpper!
  749.  
  750. currentUpper: aNumber
  751.     "Setthe current upper scale."
  752.  
  753.     currentUpper _ aNumber! !
  754.  
  755. !CollectionLabelView methodsFor: 'controller access'!
  756.  
  757. defaultControllerClass
  758.     ^NoController! !
  759.  
  760. CollectionView subclass: #GraphView
  761.     instanceVariableNames: ''
  762.     classVariableNames: ''
  763.     poolDictionaries: ''
  764.     category: 'Monitoring'!
  765. GraphView comment:
  766. 'I am a concrete class which knows how to display a collection
  767. as a line graph.  I use an instance of class Pen to draw the
  768. lines for efficiency reasons.'!
  769.  
  770.  
  771. !GraphView methodsFor: 'displaying'!
  772.  
  773. displayCollection: aCollection maxPoints: noOfPoints inBox: aRectangle scale: scaleFactor 
  774.     "Draws an appropriately scaled graph corresponding to the ordered   
  775.      collection of points aCollection, in the box aRectangle with a   
  776.      vertical scale given by scaleFactor, using the default form (black,  
  777.      extent 1@1).  Only a maximum of maxPoints points are used.  If the 
  778.      size of aCollection is less than maxPoints, then the first value in aCollection 
  779.      is repeated."
  780.  
  781.     | tempForm |
  782.     tempForm _ Form new extent: 1 @ 1.
  783.     tempForm black.
  784.     self
  785.         displayCollection: aCollection
  786.         maxPoints: noOfPoints
  787.         inBox: aRectangle
  788.         scale: scaleFactor
  789.         form: tempForm!
  790.  
  791. displayCollection: aCollection maxPoints: noOfPoints inBox: aRectangle scale: scaleFactor form: aForm 
  792.     "Draws an appropriately scaled graph corresponding to the ordered 
  793.      collection aCollection, in the box aRectangle on the display screen, 
  794.      with a vertical scale given by scaleFactor, using the form aForm.
  795.      Only a maximum of maxPoints points are used.  If the size of
  796.      aCollection is less than maxPoints, then the first value in
  797.      aCollection is repeated."
  798.  
  799.     self
  800.         displayCollection: aCollection
  801.         on: Display
  802.         maxPoints: noOfPoints
  803.         inBox: aRectangle
  804.         scale: scaleFactor
  805.         form: aForm!
  806.  
  807. displayCollection: aCollection on: aDisplayMedium maxPoints: noOfPoints inBox: aRectangle scale: scaleFactor form: aForm
  808.     "Draws an appropriately scaled graph corresponding to the ordered collection
  809.      aCollection, in the box aRectangle on aDisplayMedium, with a vertical scale
  810.      given by scaleFactor, using the form aForm.  Only a maximum of maxPoints
  811.      points are used.  If the size of aCollection is less than maxPoints, then
  812.      the first value in aCollection is repeated."
  813.  
  814.     | height width pointArray pen |
  815.     height _ aRectangle height asFloat.
  816.     width _ aRectangle width asFloat.
  817.     self pad: aCollection to: noOfPoints.
  818.     pointArray _ Array new: noOfPoints.
  819.     pen _ Pen new.
  820.     pen sourceForm: aForm.
  821.     pen destForm: aDisplayMedium.
  822.     pen frame: (aRectangle expandBy: 1).
  823.     1 to: noOfPoints do: [:x |
  824.         pointArray at: x
  825.                 put: (((x - 1) * width / (noOfPoints - 1))@
  826.                      ((scaleFactor - aCollection removeFirst) * (height/scaleFactor))) rounded
  827.                             + (aRectangle topLeft) ].
  828.     pen place: (pointArray at: 1).
  829.     2 to: noOfPoints do: [:x |
  830.         pen goto: (pointArray at: x)]! !
  831.  
  832. CollectionView subclass: #HistogramView
  833.     instanceVariableNames: ''
  834.     classVariableNames: ''
  835.     poolDictionaries: ''
  836.     category: 'Monitoring'!
  837. HistogramView comment:
  838. 'I am a concrete class which knows how to display a collection
  839. as a histogram.'!
  840.  
  841.  
  842. !HistogramView methodsFor: 'displaying'!
  843.  
  844. displayCollection: aCollection maxPoints: noOfPoints inBox: aRectangle scale: scaleFactor 
  845.     "Draws an appropriately scaled histogram corresponding to the 
  846.      ordered collection aCollection, in the box aRectangle with a vertical 
  847.      scale given by scaleFactor, using the default inside and border 
  848.      colors.  Only a maximum of maxPoints points are used. 
  849.      If the size of aCollection is less than maxPoints, then 
  850.      the first value in aCollection is repeated."
  851.  
  852.     self
  853.         displayCollection: aCollection
  854.         maxPoints: noOfPoints
  855.         inBox: aRectangle
  856.         scale: scaleFactor
  857.         insideColor: Form gray
  858.         borderColor: Form black!
  859.  
  860. displayCollection: aCollection maxPoints: noOfPoints inBox: aRectangle scale: scaleFactor insideColor: insideCol borderColor: borderCol 
  861.     "Draws an appropriately scaled histogram corresponding to the 
  862.      ordered collection aCollection, in the box aRectangle on the Display, 
  863.      with a vertical scale given by scaleFactor, using the inside and
  864.      border colors given. Only a maximum of maxPoints points are used. 
  865.      If the size of aCollection is less than maxPoints, then the first value
  866.      in aCollection is repeated."
  867.  
  868.     self
  869.         displayCollection: aCollection
  870.         on: Display
  871.         maxPoints: noOfPoints
  872.         inBox: aRectangle
  873.         scale: scaleFactor
  874.         insideColor: insideCol
  875.         borderColor: borderCol!
  876.  
  877. displayCollection: aCollection on: aDisplayMedium maxPoints: noOfPoints inBox: aRectangle scale: scaleFactor insideColor: insideCol borderColor: borderCol
  878.     "Draws an appropriately scaled histogram corresponding to the ordered
  879.      collection aCollection, in the box aRectangle on aDisplayMedium
  880.      with a vertical scale given by scaleFactor, using the inside and
  881.      border colors given. Only a maximum of maxPoints points are used.
  882.      If the size of aCollection is less than maxPoints, then
  883.      the first value in aCollection is repeated."
  884.  
  885.     | height width quadrangle previousX refPoint |
  886.     height _ aRectangle height asFloat.
  887.     width _ aRectangle width asFloat.
  888.     self pad: aCollection to: noOfPoints.
  889.     quadrangle _ Quadrangle new borderWidth: 1.
  890.     quadrangle borderColor: borderCol; insideColor: insideCol.
  891.     quadrangle left: 0; top: (height - (aCollection removeFirst * height / scaleFactor)) truncated.
  892.     quadrangle bottom: height; right: width // noOfPoints.
  893.     previousX _ quadrangle right.
  894.     refPoint _ quadrangle bottomLeft.
  895.     (quadrangle height < 1) ifTrue: [quadrangle top: (quadrangle top - 1)].
  896.     quadrangle
  897.         displayOn: aDisplayMedium
  898.         align: refPoint
  899.         with: aRectangle bottomLeft
  900.         clippingBox: aRectangle.
  901.     2 to: noOfPoints do: 
  902.         [:each | 
  903.         quadrangle left: previousX - 1.
  904.         previousX _ (each * width) // noOfPoints.
  905.         quadrangle right: previousX.
  906.         quadrangle top: (height - (aCollection removeFirst * height / scaleFactor)) truncated.
  907.     (quadrangle height < 1) ifTrue: [quadrangle top: (quadrangle top - 1)].
  908.         quadrangle
  909.             displayOn: aDisplayMedium
  910.             align: refPoint
  911.             with: aRectangle bottomLeft
  912.             clippingBox: aRectangle]! !
  913.  
  914. HistogramView subclass: #DifferenceHistogramView
  915.     instanceVariableNames: ''
  916.     classVariableNames: ''
  917.     poolDictionaries: ''
  918.     category: 'Monitoring'!
  919. DifferenceHistogramView comment:
  920. 'I am a concrete class which knows how to display a collection
  921. as a ''difference'' histogram centered around an average (mean) value.'!
  922.  
  923.  
  924. !DifferenceHistogramView methodsFor: 'displaying'!
  925.  
  926. displayCollection: aCollection on: aDisplayMedium maxPoints: noOfPoints inBox: aRectangle scale: scaleFactor insideColor: insideCol borderColor: borderCol
  927.     "Draws an appropriately scaled histogram differences diagram
  928.      corresponding to the ordered collection aCollection, in the box
  929.      aRectangle on aDisplayMedium, with a vertical scale given by
  930.      scaleFactor, using the inside and border colors. Only a maximum
  931.      of maxPoints points are used. If the size of aCollection is less
  932.      than maxPoints, then the first value in aCollection is repeated."
  933.  
  934.     | height width quadrangle previousX refPoint average halfHeight scaleHeight tempCollection |
  935.     height _ aRectangle height asFloat.
  936.     halfHeight _ height / 2.
  937.     scaleHeight _ height / scaleFactor.
  938.     width _ aRectangle width asFloat.
  939.     self pad: aCollection to: noOfPoints.
  940.     average _ self averageOf: aCollection.
  941.     tempCollection _ aCollection collect: [ :each | each - average].
  942.      quadrangle _ Quadrangle new borderWidth: 1.
  943.     quadrangle borderColor: borderCol; insideColor: insideCol.
  944.     quadrangle left: 0; right: width // noOfPoints.
  945.     previousX _ quadrangle right.
  946.     refPoint _ 0@height.
  947.     (tempCollection first > 0)
  948.     ifTrue: [
  949.         quadrangle top: (halfHeight - ((tempCollection removeFirst) * scaleHeight)) rounded.
  950.         quadrangle bottom: (halfHeight + 1) rounded.
  951.         ((quadrangle height) < 1) ifTrue: [quadrangle top: ((quadrangle top) - 1)]]
  952.     ifFalse: [
  953.         quadrangle top: halfHeight rounded.
  954.         quadrangle bottom: (halfHeight - ((tempCollection removeFirst)  * scaleHeight)) rounded.
  955.         ((quadrangle height) < 1) ifTrue: [quadrangle bottom: ((quadrangle bottom) + 1)]].
  956.     quadrangle
  957.         displayOn: aDisplayMedium
  958.         align: refPoint
  959.         with: aRectangle bottomLeft
  960.         clippingBox: aRectangle.
  961.     2 to: noOfPoints do: [:each | 
  962.         ((tempCollection first) > 0)
  963.         ifTrue: [
  964.             quadrangle top: (halfHeight - ((tempCollection removeFirst) * scaleHeight)) rounded.
  965.             quadrangle bottom: (halfHeight + 1) rounded.
  966.             ((quadrangle height) < 1) ifTrue: [quadrangle top: ((quadrangle top) - 1)]]
  967.         ifFalse: [
  968.             quadrangle top: halfHeight rounded.
  969.             quadrangle bottom: (halfHeight - ((tempCollection removeFirst)  * scaleHeight)) rounded.
  970.             ((quadrangle height) < 1) ifTrue: [quadrangle bottom: ((quadrangle bottom) + 1)]].
  971.         quadrangle left: previousX - 1.
  972.         previousX _ (each * width) // noOfPoints.
  973.         quadrangle right: previousX.
  974.         quadrangle
  975.             displayOn: aDisplayMedium
  976.             align: refPoint
  977.             with: aRectangle bottomLeft
  978.             clippingBox: aRectangle]! !
  979.  
  980. View subclass: #MonitorView
  981.     instanceVariableNames: 'project currentStyle currentDisplay displayPoints displayCount currentDisplayCount currentUpper currentLower '
  982.     classVariableNames: 'BitBltScale CoreScale CpuScale DefaultCount DefaultDisplay DefaultDisplayPoints DefaultStyle FileScale InputScale OopsScale ProcessScale '
  983.     poolDictionaries: ''
  984.     category: 'Monitoring'!
  985. MonitorView comment:
  986. 'I represent a View of a system monitoring process.  My
  987. subviews can display one aspect of the system activity
  988. in a variety of ways.  My instance variables are:
  989.  
  990. project            The project in which I am to display.
  991.  
  992. currentStyle    The display style to be used (graph, histogram, etc).
  993.                 I rebuild my subviews when this is changed.
  994.  
  995. currentDisplay    The system history I currently represent.
  996.  
  997. displayPoints    The number of records in the history I display.
  998.  
  999. currentDisplayCount    A counter which is incremented every time
  1000.                 the monitoring process is run.  When this reaches
  1001.                 displayCount, I update my display.
  1002.  
  1003. currentUpper    The upper scaled value I am using when displaying.
  1004.  
  1005. currentLower    The lower scaled value I am using when displaying.
  1006. '!
  1007.  
  1008.  
  1009. !MonitorView methodsFor: 'initialize-release'!
  1010.  
  1011. initialize
  1012.     "Initialize the project, style and displayed parameter associated with 
  1013.      this view."
  1014.  
  1015.     super initialize.
  1016.     self currentProject: Project current.
  1017.     self currentDisplay: DefaultDisplay.
  1018.     self currentStyle: DefaultStyle.
  1019.     self displayPoints: DefaultDisplayPoints.
  1020.     self currentDisplayCount: 0.
  1021.     self displayCount: DefaultCount! !
  1022.  
  1023. !MonitorView methodsFor: 'count access'!
  1024.  
  1025. currentDisplayCount
  1026.     "Answer with the current display count."
  1027.  
  1028.     ^currentDisplayCount!
  1029.  
  1030. currentDisplayCount: aNumber
  1031.     "Set the current display count."
  1032.  
  1033.     currentDisplayCount _ aNumber!
  1034.  
  1035. displayCount
  1036.     "Answer with the display count."
  1037.  
  1038.     ^displayCount!
  1039.  
  1040. displayCount: aNumber
  1041.     "Set the display count."
  1042.  
  1043.     displayCount _ aNumber!
  1044.  
  1045. displayInterval
  1046.     "Answer with the time between successive displays."
  1047.  
  1048.     ^displayCount * self model delayInterval!
  1049.  
  1050. displayInterval: aNumber
  1051.     "Set the time between successive displays."
  1052.  
  1053.     self displayCount: aNumber // self model delayInterval!
  1054.  
  1055. incrementDisplayCount
  1056.  
  1057.     currentDisplayCount _ currentDisplayCount + 1! !
  1058.  
  1059. !MonitorView methodsFor: 'project access'!
  1060.  
  1061. currentProject
  1062.     "Answers with my project."
  1063.  
  1064.     ^project!
  1065.  
  1066. currentProject: aProject 
  1067.     "Sets my project."
  1068.  
  1069.     project _ aProject! !
  1070.  
  1071. !MonitorView methodsFor: 'display access'!
  1072.  
  1073. currentCollection
  1074.     "Answer with a collection corresponding the current
  1075.      displayed history."
  1076.  
  1077.     | disp |
  1078.     disp _ self currentDisplay.
  1079.     disp == #memory ifTrue: [^self model coreHistory].
  1080.     disp == #oops ifTrue: [^self model oopsHistory].
  1081.     disp == #input ifTrue: [^self model inputHistory].
  1082.     disp == #bitblt ifTrue: [^self model bitBltHistory].
  1083.     disp == #files ifTrue: [^self model fileHistory].
  1084.     disp == #cpu ifTrue: [^self model activityHistory].
  1085.     disp == #process ifTrue: [^self model processHistory].
  1086.     self error: 'Attempt to display non-existent history'!
  1087.  
  1088. currentDisplay
  1089.     "Returns the current display (e.g CPU activity, core left)."
  1090.  
  1091.     ^currentDisplay!
  1092.  
  1093. currentDisplay: aValue
  1094.     "Sets the current display (e.g BitBlt count, file activity)."
  1095.  
  1096.     currentDisplay _ aValue!
  1097.  
  1098. currentLower
  1099.     "Answer with the current lower scale value."
  1100.  
  1101.     ^currentLower!
  1102.  
  1103. currentLower: aNumber
  1104.     "Set the current lower scale value."
  1105.  
  1106.     currentLower _ aNumber!
  1107.  
  1108. currentStyle
  1109.     "Answers the current display style (e.g Graph or Histogram)."
  1110.  
  1111.     ^currentStyle!
  1112.  
  1113. currentStyle: aSymbol
  1114.     "Sets the current display style (e.g Graph Bar chart or Histogram)."
  1115.  
  1116.     currentStyle _ aSymbol!
  1117.  
  1118. currentUpper
  1119.     "Answer with the current upper scale value."
  1120.  
  1121.     ^currentUpper!
  1122.  
  1123. currentUpper: aNumber
  1124.     "Set the current upper scale value."
  1125.  
  1126.     currentUpper _ aNumber!
  1127.  
  1128. displayPoints
  1129.     "Answers with the number of displayed points."
  1130.  
  1131.     ^displayPoints!
  1132.  
  1133. displayPoints: aNumber
  1134.     "Sets the number of displayed points to aNumber."
  1135.  
  1136.     displayPoints _ aNumber! !
  1137.  
  1138. !MonitorView methodsFor: 'displaying'!
  1139.  
  1140. displaySubViews
  1141.     "Override to make sure that we do not update the display when
  1142.      collapsed, or when we are in a different project."
  1143.  
  1144.     self currentDisplayCount: 0.
  1145.     (self topView isCollapsed not and: [Project current == self currentProject]) ifTrue: [
  1146.         self buildScaleFactors.
  1147.         super displaySubViews].!
  1148.  
  1149. update: aParameter
  1150.     "Increment the display count.  If this is large enough, then
  1151.      re-display the receiver."
  1152.  
  1153.     self incrementDisplayCount.
  1154.     self currentDisplayCount >= self displayCount ifTrue: [
  1155.          self displaySubViews]! !
  1156.  
  1157. !MonitorView methodsFor: 'private'!
  1158.  
  1159. buildScaleFactors
  1160.     "Determine the current upper and lower scale factors, depending
  1161.      on the history which is to be displayed."
  1162.  
  1163.     self currentUpper: (self scaleUpper: self currentCollection to: self currentScaleStep).
  1164.     self currentLower: (self scaleLower: self currentCollection to: self currentScaleStep)!
  1165.  
  1166. buildSubViews
  1167.     "Construct the subViews associated with the receiver.  Release
  1168.      any existing subViews first."
  1169.  
  1170.     | aCollectionView aLabelView |
  1171.     self releaseSubViews.
  1172.     aCollectionView _ self currentStyleView.
  1173.     aCollectionView model: SystemMonitor.
  1174.     aCollectionView insideColor: Form white.
  1175.     aCollectionView borderColor: Form white.
  1176.     aCollectionView borderWidth: 2.
  1177.     self addSubView: aCollectionView viewport: (0@0 corner: 100@70).
  1178.  
  1179.     aLabelView _ CollectionLabelView new.
  1180.     aLabelView model: SystemMonitor.
  1181.     aLabelView borderWidth: 2.
  1182.     aLabelView borderColor: Form white.
  1183.     aLabelView insideColor: Form white.
  1184.     self addSubView: aLabelView viewport: (0@70 corner: 100@100)!
  1185.  
  1186. currentScaleStep
  1187.     "Answer with a scale step factor appropriate for the current
  1188.      displayed history."
  1189.  
  1190.     | disp |
  1191.     disp _ self currentDisplay.
  1192.     disp == #memory ifTrue: [^CoreScale].
  1193.     disp == #oops ifTrue: [^OopsScale].
  1194.     disp == #input ifTrue: [^InputScale].
  1195.     disp == #bitblt ifTrue: [^BitBltScale].
  1196.     disp == #files ifTrue: [^FileScale].
  1197.     disp == #cpu ifTrue: [^CpuScale].
  1198.     disp == #process ifTrue: [^ProcessScale].
  1199.     self error: 'Attempt to use inappropriate scale factor'!
  1200.  
  1201. currentStyleView
  1202.     "Answer with an instance of the subclass of CollectionView corresponding
  1203.      to the current display style."
  1204.  
  1205.     self currentStyle == #graph ifTrue: [^GraphView new].
  1206.     self currentStyle == #histogram ifTrue: [^HistogramView new].
  1207.     self currentStyle == #difference ifTrue: [^DifferenceHistogramView new].
  1208.     self currentStyle == #barchart ifTrue: [^BarStripView new].
  1209.     self error: 'Attempt to use non-existant display style'!
  1210.  
  1211. scaleLower: aCollection to: aNumber 
  1212.     "Answer with a number which is the smallest value in aCollection, 
  1213.      rounded down to multiples of aNumber"
  1214.  
  1215.     | min |
  1216.     min _ aCollection first.
  1217.     aCollection do: [:each |
  1218.         (each < min) ifTrue: [min _ each]].
  1219.     ^min truncateTo: aNumber!
  1220.  
  1221. scaleUpper: aCollection to: aNumber 
  1222.     "Answer with a number which is the largest value in aCollection, 
  1223.      rounded up to multiples of aNumber"
  1224.  
  1225.     | max |
  1226.     max _ aCollection first.
  1227.     aCollection do: [:each |
  1228.         (each > max) ifTrue: [max _ each]].
  1229.     ^(max + aNumber) truncateTo: aNumber! !
  1230. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1231.  
  1232. MonitorView class
  1233.     instanceVariableNames: ''!
  1234.  
  1235.  
  1236. !MonitorView class methodsFor: 'class initialization'!
  1237.  
  1238. initialize
  1239.     "Initialize various default values."
  1240.  
  1241.     DefaultDisplay _ #memory.
  1242.     DefaultDisplayPoints _ 50.
  1243.     DefaultStyle _ #graph.
  1244.     DefaultCount _ 6.
  1245.  
  1246.     BitBltScale _ 100.
  1247.     CoreScale _ 5000.
  1248.     FileScale _ 10.
  1249.     InputScale _ 50.
  1250.     OopsScale _ 500.
  1251.     CpuScale _ 200.
  1252.     ProcessScale _ 5.
  1253.  
  1254.     "MonitorView initialize."! !
  1255.  
  1256. !MonitorView class methodsFor: 'instance creation'!
  1257.  
  1258. open
  1259.     "Create a view on the system monitoring process."
  1260.     "MonitorView open."
  1261.  
  1262.     | topView monitorView |
  1263.     topView _ StandardSystemView new.
  1264.     topView label: 'Monitor'.
  1265.     topView borderWidth: 2.
  1266.     topView insideColor: Form white.
  1267.     topView minimumSize: 200@75.
  1268.  
  1269.     monitorView _ self new    .
  1270.     monitorView model: SystemMonitor.
  1271.     monitorView controller: (MonitorController new sensor: InputSensor default).
  1272.     monitorView window: (0@0 extent: 100@100).
  1273.     topView addSubView: monitorView.
  1274.  
  1275.     monitorView buildSubViews.
  1276.  
  1277.     topView controller open.! !
  1278.  
  1279. MonitorView initialize!
  1280.  
  1281.  
  1282. MonitorView subclass: #LargeMonitorView
  1283.     instanceVariableNames: ''
  1284.     classVariableNames: ''
  1285.     poolDictionaries: ''
  1286.     category: 'Monitoring'!
  1287. LargeMonitorView comment:
  1288. 'I represent a View of a system monitoring process.  I can display all
  1289. the history traces simultaneously.
  1290. '!
  1291.  
  1292.  
  1293. !LargeMonitorView methodsFor: 'displaying'!
  1294.  
  1295. displaySubViews
  1296.     "Make sure that we do not update the display when
  1297.      collapsed, or when we are in a different project.  Display
  1298.      the subviews in the order given by dispArray."
  1299.  
  1300.     | dispArray |
  1301.     self currentDisplayCount: 0.
  1302.     (self topView isCollapsed not and: [Project current == self currentProject]) ifTrue: [
  1303.         dispArray _ #( #cpu #process #memory #oops #input #bitblt #files).
  1304.         1 to: 7 do: [ :each |
  1305.             self currentDisplay: (dispArray at: each).
  1306.             self buildScaleFactors.
  1307.         (self subViews at: (2 * each - 1)) display.
  1308.         (self subViews at: (2 * each)) display.
  1309.         Processor yield]]! !
  1310.  
  1311. !LargeMonitorView methodsFor: 'private'!
  1312.  
  1313. buildSubViews
  1314.     "Construct the subviews associated with the receiver.  Release
  1315.      any existing subViews first."
  1316.  
  1317.     | aCollectionView aLabelView |
  1318.     self releaseSubViews.
  1319.     0 to: 6 do: [ :each |
  1320.         aCollectionView _ self currentStyleView.
  1321.         aCollectionView model: SystemMonitor.
  1322.         aCollectionView insideColor: Form white.
  1323.         aCollectionView borderColor: Form white.
  1324.         aCollectionView borderWidth: 1.
  1325.         self
  1326.             addSubView: aCollectionView
  1327.             viewport: (0@(each * 100) corner: 100@(each * 100 + 70)).
  1328.         aLabelView _ CollectionLabelView new.
  1329.         aLabelView model: SystemMonitor.
  1330.         aLabelView borderWidth: 1.
  1331.         aLabelView borderColor: Form white.
  1332.         aLabelView insideColor: Form white.
  1333.         self
  1334.             addSubView: aLabelView
  1335.             viewport: (0@(each * 100 + 70) corner: 100@(each + 1 * 100))]! !
  1336. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1337.  
  1338. LargeMonitorView class
  1339.     instanceVariableNames: ''!
  1340.  
  1341.  
  1342. !LargeMonitorView class methodsFor: 'instance creation'!
  1343.  
  1344. open
  1345.     "Create a multiple view on the system monitoring process."
  1346.     "LargeMonitorView open."
  1347.  
  1348.     | topView monitorView |
  1349.     topView _ StandardSystemView new.
  1350.     topView label: 'System Monitoring'.
  1351.     topView borderWidth: 2.
  1352.     topView insideColor: Form white.
  1353.     topView minimumSize: 200@385.
  1354.  
  1355.     monitorView _ self new.
  1356.     monitorView model: SystemMonitor.
  1357.     monitorView controller: (LargeMonitorController new sensor: InputSensor default).
  1358.     monitorView window: (0@0 extent: 100@700).
  1359.     topView addSubView: monitorView.
  1360.  
  1361.     monitorView buildSubViews.
  1362.  
  1363.     topView controller open.! !
  1364.  
  1365.  
  1366. 'From Smalltalk-80, version 2, of April 1, 1983 on 22 July 1987 at 5:11:17 pm'!
  1367.  
  1368.  
  1369.  
  1370. !BitBlt methodsFor: 'private'!
  1371.  
  1372. reallyCopyBits
  1373.     "Perform the movement of bits from one From to another described by the instance variables of the receiver.  Fail if any instance variables are not of the right type (Integer or Form) or if combinationRule is not between 0 and 15 inclusive.  Set the variables and try again (BitBlt|copyBitsAgain).  Essential.  See Object documentation whatIsAPrimitive."
  1374.  
  1375.     <primitive: 96>
  1376.     combinationRule = Form paint
  1377.         ifTrue: [^self paintBits]
  1378.         ifFalse:
  1379.             [destX _ destX truncated.
  1380.             destY _ destY truncated.
  1381.             width _ width truncated.
  1382.             height _ height truncated.
  1383.             sourceX _ sourceX truncated.
  1384.             sourceY _ sourceY truncated.
  1385.             clipX _ clipX truncated.
  1386.             clipY _ clipY truncated.
  1387.             clipWidth _ clipWidth truncated.
  1388.             clipHeight _ clipHeight truncated.
  1389.             ^self copyBitsAgain]! !
  1390.  
  1391. 'From Smalltalk-80, version 2, of April 1, 1983 on 22 July 1987 at 5:11:24 pm'!
  1392.  
  1393.  
  1394.  
  1395. !BitBlt methodsFor: 'copying'!
  1396.  
  1397. copyBits
  1398.     SystemMonitor incrementBitBltCount.    "For system monitoring."
  1399.     self reallyCopyBits! !
  1400.  
  1401. 'From Smalltalk-80, version 2, of April 1, 1983 on 22 July 1987 at 5:11:46 pm'!
  1402.  
  1403.  
  1404.  
  1405. !CharacterBlockScanner methodsFor: 'private'!
  1406.  
  1407. buildCharacterBlockIn: aParagraph
  1408.     | lineIndex runLength lineStop characterBlock done stopCondition |
  1409.     "handle nullText"
  1410.     (aParagraph numberOfLines = 0 or: [text size = 0])
  1411.         ifTrue:    [leftMargin _ (aParagraph leftMarginForDisplayForLine: 1).
  1412.                 ^CharacterBlock
  1413.                     stringIndex: 1    "like being off end of string"
  1414.                     character: nil
  1415.                     topLeft: (leftMargin @
  1416.                                 (aParagraph compositionRectangle) top)
  1417.                     extent: (0 @ textStyle lineGrid)].
  1418.  
  1419.     "find the line"
  1420.     lineIndex _ aParagraph lineIndexOfTop: characterPoint y.
  1421.     destY _ (aParagraph topAtLineIndex: lineIndex).
  1422.     line _ aParagraph lineAt: lineIndex.
  1423.     text _ aParagraph textAt: lineIndex.
  1424.     rightMargin _ aParagraph rightMarginForDisplay.
  1425.  
  1426.     (lineIndex = aParagraph numberOfLines and:
  1427.         [(destY + textStyle lineGrid) < characterPoint y])
  1428.             ifTrue:    ["if beyond lastLine, force search to last character"
  1429.                     characterPoint x: rightMargin]
  1430.             ifFalse:    [characterPoint y < (aParagraph compositionRectangle) top
  1431.                         ifTrue: ["force search to first line"
  1432.                                 characterPoint _
  1433.                                 (aParagraph compositionRectangle) topLeft].
  1434.                     characterPoint x > rightMargin
  1435.                         ifTrue:    [characterPoint x: rightMargin]].
  1436.     destX _ leftMargin _ aParagraph leftMarginForDisplayForLine: lineIndex.
  1437.     nextLeftMargin_ aParagraph leftMarginForDisplayForLine: lineIndex+1.
  1438.     lastIndex _ line first.
  1439.  
  1440.     self setStopConditions.        "also sets font"
  1441.     runLength _ (text runLengthFor: line first).
  1442.     characterIndex ~~ nil
  1443.         ifTrue:    [lineStop _ characterIndex    "scanning for index"]
  1444.         ifFalse:    [lineStop _ line last].
  1445.     (runStopIndex _ lastIndex + (runLength - 1)) > lineStop
  1446.         ifTrue:    [runStopIndex _ lineStop].
  1447.     lastCharacterExtent _ 0 @ textStyle lineGrid.
  1448.     spaceCount _ 0. done  _ false.
  1449.  
  1450.     [done]
  1451.     whileFalse:
  1452.     [SystemMonitor incrementBitBltCount. "For system monitoring."
  1453.      stopCondition _ 
  1454.                     self scanCharactersFrom: lastIndex
  1455.                         to: runStopIndex
  1456.                         in: text string
  1457.                         rightX: characterPoint x
  1458.                         stopConditions: stopConditions
  1459.                         displaying: false.
  1460.  
  1461.         "see setStopConditions for stopping conditions for character block     operations."
  1462.     lastCharacterExtent x: (font widthOf: (text at: lastIndex)).
  1463.     (self perform: stopCondition)
  1464.         ifTrue:    [^CharacterBlock
  1465.                     stringIndex: lastIndex
  1466.                     character: lastCharacter
  1467.                     topLeft: characterPoint
  1468.                     extent: lastCharacterExtent]]! !
  1469.  
  1470. 'From Smalltalk-80, version 2, of April 1, 1983 on 22 July 1987 at 5:11:56 pm'!
  1471.  
  1472.  
  1473.  
  1474. !CharacterScanner methodsFor: 'scanning'!
  1475.  
  1476. characterNotInFont
  1477.     "All fonts have an illegal character to be used when a character is not within the font's legal range.  When characters out of ranged are encountered in scanning text, then this special character indicates the appropriate behavior.  The character is usually treated as a unary message understood by a subclass of CharacterScanner."
  1478.  
  1479.     | illegalAsciiString saveIndex stopCondition | 
  1480.     saveIndex _ lastIndex.
  1481.     illegalAsciiString _ String with: (font maxAscii + 1) asCharacter.
  1482.     (self isMemberOf: CompositionScanner) not
  1483.     ifTrue: [
  1484.     SystemMonitor incrementBitBltCount. "For system monitoring."
  1485.     stopCondition _ 
  1486.                     self scanCharactersFrom: 1
  1487.                         to: 1
  1488.                         in: illegalAsciiString
  1489.                         rightX: rightMargin
  1490.                         stopConditions: stopConditions
  1491.                         displaying: self doesDisplaying]
  1492.     ifFalse:    [
  1493.     stopCondition _ 
  1494.         self scanCharactersFrom: 1 to: 1
  1495.             in: illegalAsciiString
  1496.             rightX: rightMargin stopConditions: stopConditions
  1497.             displaying: self doesDisplaying].
  1498.     lastIndex _ saveIndex + 1.
  1499.     stopCondition ~= (stopConditions at: EndOfRun)
  1500.         ifTrue:    [^self perform: stopCondition]
  1501.         ifFalse: [lastIndex = runStopIndex
  1502.                     ifTrue:    [^self perform: (stopConditions at: EndOfRun)].
  1503.                 ^false]! !
  1504.  
  1505. 'From Smalltalk-80, version 2, of April 1, 1983 on 22 July 1987 at 5:12:08 pm'!
  1506.  
  1507.  
  1508.  
  1509. !CompositionScanner methodsFor: 'scanning'!
  1510.  
  1511. composeLine: lineIndex fromCharacterIndex: startIndex inParagraph: aParagraph
  1512.     "Answer an instance of TextLineInterval that represents the next line in the paragraph."
  1513.  
  1514.     | runLength done stopCondition |
  1515.     lastIndex _ startIndex.        "scanning sets last index"
  1516.     self setStopConditions.        "also sets font"
  1517.     spaceX _ destX _ leftMargin _
  1518.         (aParagraph leftMarginForCompositionForLine: lineIndex).
  1519.     rightMargin _ aParagraph rightMarginForComposition.
  1520.     leftMargin >= rightMargin ifTrue:
  1521.         [self error: 'No room between margins to compose'].
  1522.     runLength _ text runLengthFor: startIndex.
  1523.     runStopIndex _ (lastIndex _ startIndex) + (runLength - 1).
  1524.     line _ 
  1525.         TextLineInterval
  1526.             start: lastIndex stop: 0 internalSpaces: 0 paddingWidth: 0.
  1527.     spaceCount _ 0.
  1528.     done _ false.
  1529.     [done]
  1530.         whileFalse: 
  1531.             [SystemMonitor incrementBitBltCount. "For system monitoring."
  1532.              stopCondition _ 
  1533.                 self 
  1534.                     scanCharactersFrom: lastIndex
  1535.                     to: runStopIndex
  1536.                     in: text string
  1537.                     rightX: rightMargin
  1538.                     stopConditions: stopConditions
  1539.                     displaying: false.
  1540.             "See setStopConditions for stopping conditions for composing."
  1541.             (self perform: stopCondition) ifTrue: [^line]]! !
  1542.  
  1543. 'From Smalltalk-80, version 2, of April 1, 1983 on 22 July 1987 at 5:12:18 pm'!
  1544.  
  1545.  
  1546.  
  1547. !DisplayScanner methodsFor: 'scanning'!
  1548.  
  1549. displayLines: linesInterval in: aParagraph clippedBy: visibleRectangle
  1550.     "The central display routine.  The call on the primitive (scanCharactersFrom:to:in:rightX:) will be interrupted according to the StopConditions array passed to the primitive at which time the code to handle the stopCondition is run and the call on the primitive continued until a stopCondition returns true which means the line has terminated."
  1551.  
  1552.     | runLength done lineGrid lineIndex stopCondition displaying|
  1553.  
  1554.     self initializeFromParagraph: aParagraph clippedBy: visibleRectangle.
  1555.     rightMargin _ aParagraph rightMarginForDisplay.
  1556.     lineGrid _ textStyle lineGrid.
  1557.     "assume outputMedium Display"
  1558.     lineY _ destY _
  1559.                     aParagraph topAtLineIndex: linesInterval first.
  1560.     displaying _ self doesDisplaying.
  1561.     linesInterval do: 
  1562.         [:lineIndex | 
  1563.         runX _ destX _ leftMargin _
  1564.             aParagraph leftMarginForDisplayForLine: lineIndex.
  1565.         line _ aParagraph lineAt: lineIndex.
  1566.         text _ aParagraph textAt: lineIndex.
  1567.         lastIndex _ line first.
  1568.         self setStopConditions.    "also sets the font"
  1569.         destY _ lineY + self fontAscentDelta.        "fontAscent delta".
  1570.  
  1571.         runLength _ text runLengthFor: line first.
  1572.         (runStopIndex _ lastIndex + (runLength - 1)) > line last 
  1573.             ifTrue: [runStopIndex _ line last].
  1574.         spaceCount _ 0.
  1575.         done _ false.
  1576.         [done]
  1577.             whileFalse: 
  1578.                 [SystemMonitor incrementBitBltCount. "For system monitoring."
  1579.                  stopCondition _ 
  1580.                                 self scanCharactersFrom: lastIndex
  1581.                                     to: runStopIndex
  1582.                                     in: text string
  1583.                                     rightX: rightMargin
  1584.                                     stopConditions: stopConditions
  1585.                                     displaying: displaying.
  1586.                 "see setStopConditions for stopping conditions for displaying."
  1587.                 done _ self perform: stopCondition].
  1588.             "Y origin upper left -- increases as moving down page."
  1589.                     lineY _ lineY + lineGrid].
  1590.         ^lineIndex! !
  1591.  
  1592. 'From Smalltalk-80, version 2, of April 1, 1983 on 22 July 1987 at 5:12:25 pm'!
  1593.  
  1594.  
  1595.  
  1596. !InputSensor methodsFor: 'private'!
  1597.  
  1598. buttons
  1599.     SystemMonitor incrementActivityCount.    "For system monitoring."
  1600.     ^self primMouseButtons! !
  1601.  
  1602. 'From Smalltalk-80, Version 2.2 of July 4, 1987 on 26 November 1987 at 11:32:34 am'!
  1603.  
  1604. !InputState methodsFor: 'private'!
  1605.  
  1606. reallyPrimInputWord
  1607.     "Return the next word from the input buffer and remove the word from the 
  1608.     buffer. This message should be sent just after the input semaphore 
  1609.     finished a wait (was sent a signal by an I/O device). Fail of the input 
  1610.     buffer is empty. Essential. See Object documentation whatIsAPrimitive."
  1611.  
  1612.     <primitive: 95>
  1613.     ^self primitiveFailed! !
  1614.  
  1615. 'From Smalltalk-80, Version 2.2 of July 4, 1987 on 26 November 1987 at 11:32:45 am'!
  1616.  
  1617. !InputState methodsFor: 'private'!
  1618.  
  1619. primInputWord
  1620.     "Increment a counter for system monitoring, and then really do the primitive."
  1621.  
  1622.     SystemMonitor incrementInputCount. "Counter for system monitoring."
  1623.     ^self reallyPrimInputWord! !
  1624.  
  1625.  
  1626. 'From Smalltalk-80, version 2, of April 1, 1983 on 22 July 1987 at 5:39:34 pm'!
  1627.  
  1628. !UnixSystemCall methodsFor: 'execution'!
  1629.  
  1630. reallyInvokeIfFail: aBlock
  1631.     "Invoke myself as a Unix system call."
  1632.  
  1633.     <primitive: 244>
  1634.     ^aBlock value! !
  1635.  
  1636. 'From Smalltalk-80, version 2, of April 1, 1983 on 22 July 1987 at 5:12:45 pm'!
  1637.  
  1638.  
  1639.  
  1640. !UnixSystemCall methodsFor: 'execution'!
  1641.  
  1642. invokeIfFail: aBlock
  1643.  
  1644.     SystemMonitor incrementFileCount.  "Counter for I/O activity (monitor)."
  1645.     ^self reallyInvokeIfFail: aBlock! !
  1646.  
  1647.